package com.shortchainsystem.link.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shortchainsystem.link.mapper.*;
import com.shortchainsystem.link.service.LinkStatsService;
import com.shortchainsystem.model.domain.link.*;
import com.shortchainsystem.model.domain.link.DTO.StaticDTO;
import com.shortchainsystem.model.exception.CustomCodeEnum;
import com.shortchainsystem.util.RandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class LinkStatsServiceImpl extends ServiceImpl<LinkStatsMapper, LinkStats> implements LinkStatsService {
    @Autowired
    private LinkStatsMapper linkStatsMapper;
    @Autowired
    private LinkOsStatsMapper linkOsStatsMapper;
    @Autowired
    private LinkDeviceStatsMapper linkDeviceStatsMapper;
    @Autowired
    private LinkLocateStatsMapper linkLocateStatsMapper;
    @Autowired
    private LinkBrowserStatsMapper linkBrowserStatsMapper;

    @Override
    @Async
    @Transactional
    public void insertOne(LinkStats linkStats) {
        // 1、判断该链接数据是否已存在
        List<LinkStats> statsList = linkStatsMapper.selectList(new LambdaQueryWrapper<LinkStats>()
                .eq(LinkStats::getLinkId, linkStats.getLinkId())
                .eq(LinkStats::getUserId, linkStats.getUserId())
                .eq(LinkStats::getIpAddress, linkStats.getIpAddress())
                .eq(LinkStats::getOs, linkStats.getOs())
                .eq(LinkStats::getDevice, linkStats.getDevice())
                .eq(LinkStats::getBrowser, linkStats.getBrowser())
                .eq(LinkStats::getIpLocation, linkStats.getIpLocation()));
        LinkStats linkStatsData = null;
        if(statsList.size()==1) linkStatsData = statsList.get(0);
        else if(statsList.size()>1) return;

        // 2、存在则更新访问次数，不存在则新增
        if (linkStatsData != null) {
            linkStatsData.setVisitCount(linkStatsData.getVisitCount() + 1);
            linkStatsMapper.updateById(linkStatsData);
        } else {
            linkStatsData = linkStats;
            linkStatsData.setVisitCount(1);
            linkStatsData.setId(RandomUtil.getRandom(10));
            linkStatsMapper.insert(linkStatsData);
        }

        // 3、统计访问设备
        LinkDeviceStats linkDeviceStats = new LinkDeviceStats();
        linkDeviceStats.setId(RandomUtil.getRandom(10));
        linkDeviceStats.setLinkStatsId(linkStatsData.getId());
        linkDeviceStats.setDevice(linkStatsData.getDevice());
        linkDeviceStatsMapper.insert(linkDeviceStats);

        // 4、统计访问IP地址和IP归属地
        LinkLocateStats linkLocateStats = new LinkLocateStats();
        linkLocateStats.setId(RandomUtil.getRandom(10));
        linkLocateStats.setLinkStatsId(linkStatsData.getId());
        linkLocateStats.setIpAddress(linkStatsData.getIpAddress());
        linkLocateStats.setIpLocation(linkStatsData.getIpLocation());
        linkLocateStatsMapper.insert(linkLocateStats);

        // 5、统计访问浏览器
        LinkBrowserStats linkBrowserStats = new LinkBrowserStats();
        linkBrowserStats.setId(RandomUtil.getRandom(10));
        linkBrowserStats.setLinkStatsId(linkStatsData.getId());
        linkBrowserStats.setBrowser(linkStatsData.getBrowser());
        linkBrowserStatsMapper.insert(linkBrowserStats);

        // 6、统计访问系统
        LinkOsStats linkOsStats = new LinkOsStats();
        linkOsStats.setId(RandomUtil.getRandom(10));
        linkOsStats.setLinkStatsId(linkStatsData.getId());
        linkOsStats.setOs(linkStatsData.getOs());
        linkOsStatsMapper.insert(linkOsStats);
    }

    @Override
    public void deleteAll(String linkId) {
        // 获取该短链的所有短链数据
        List<LinkStats> linkStatsList = linkStatsMapper.selectList(new LambdaQueryWrapper<LinkStats>().eq(LinkStats::getLinkId,linkId));
        // 逐一删除
        linkStatsList.forEach(linkStats -> {
            linkDeviceStatsMapper.delete(new LambdaQueryWrapper<LinkDeviceStats>().eq(LinkDeviceStats::getLinkStatsId, linkStats.getId()));
            linkLocateStatsMapper.delete(new LambdaQueryWrapper<LinkLocateStats>().eq(LinkLocateStats::getLinkStatsId, linkStats.getId()));
            linkBrowserStatsMapper.delete(new LambdaQueryWrapper<LinkBrowserStats>().eq(LinkBrowserStats::getLinkStatsId, linkStats.getId()));
            linkOsStatsMapper.delete(new LambdaQueryWrapper<LinkOsStats>().eq(LinkOsStats::getLinkStatsId,linkStats.getId()));
        });
        if(linkStatsList.size()!=0) linkStatsMapper.deleteBatchIds(linkStatsList);
    }

    @Override
    public List<LinkStats> getAllLinkStats(List<Link> links, StaticDTO staticDTO) {
        // 1、获取所有的短链数据
        List<LinkStats> linkStatsList = linkStatsMapper.selectList(new LambdaQueryWrapper<LinkStats>()
                .in(LinkStats::getLinkId, links.stream().map(Link::getId).collect(Collectors.toList())));
        if(staticDTO!=null){
            // 2、判断时间范围类型
            int days = 0;
            if(staticDTO.getTimeType().equals("1")) days = 1;
            else if(staticDTO.getTimeType().equals("2")) days = 3;
            else if(staticDTO.getTimeType().equals("3")) days = 7;
            else if(staticDTO.getTimeType().equals("4")) days = 30;
            else if(staticDTO.getTimeType().equals("5")) days = 365;
            // 3、进行时间、操作系统、访问环境筛选，其中0默认为永久
            if(days!=0){
                LocalDateTime startDateTime = LocalDateTime.now().minusDays(days);
                linkStatsList = linkStatsList.stream()
                        .filter(linkStats -> linkStats.getCreateTime().isAfter(startDateTime))
                        .filter(linkStats -> {
                            if(!staticDTO.getBrowser().equals("all")){
                                return linkStats.getBrowser().equals(staticDTO.getBrowser());
                            }
                            return true;    // 不进行过滤
                        })
                        .filter(linkStats -> {
                            if(!staticDTO.getOs().equals("all")){
                                return linkStats.getOs().equals(staticDTO.getOs());
                            }
                            return true;    // 不进行过滤
                        })
                        .collect(Collectors.toList());
            }
        }
        return linkStatsList;
    }
}